local function music_recharge(inst)
	if inst.components.musha_skills.skill_point["Music"]:value() > 0 then
		local music_multiple = inst.components.musha_skills.skill_point["Music"]:value() == 2 and 0.65 or 1
		local fire =
			FindEntity(
			inst,
			6,
			function(ent)
				return ent.components.burnable and ent.components.burnable:IsBurning()
			end,
			{"campfire"}
		)
		local yamche =
			FindEntity(
			inst,
			6,
			function(ent)
				return ent.components.burnable and ent.components.burnable:IsBurning()
			end,
			{"musha_yamche"}
		)
		if fire or yamche then
			inst.with_fire = true
		else
			inst.with_fire = false
		end
		if inst.with_tent then
			inst.components.musha_skills.data.music =
				math.min(
				inst.components.musha_skills.data.music + 0.2 * inst.musha_settings.music_recharge_multiple / music_multiple,
				100
			)
		elseif inst.with_fire then
			inst.components.musha_skills.data.music =
				math.min(
				inst.components.musha_skills.data.music + 0.1 * inst.musha_settings.music_recharge_multiple / music_multiple,
				100
			)
		else
			return
		end
		inst.components.talker:Say(STRINGS.Musha_Skills.MUSIC .. " " .. inst.components.musha_skills.data.music .. "%")
	end
end

local function Expeat(inst, food)
	--dislike food type
	if food.prefab == "musha_apple" or food.prefab == "musha_apple_cooked" then
		inst:PushEvent("musha_gainexp", 3)
	elseif food.prefab == "musha_glowdust" then
		inst:PushEvent("musha_gainexp", 5)
	elseif inst.musha_settings.dis_food_type == food.components.edible.foodtype then
		inst:DoTaskInTime(
			0.7,
			function()
				inst.sg:GoToState("refuseeat")
				local random_chance = math.random()
				if random_chance < 0.33 then
					inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_FOOD_BAD))
				elseif random_chance < 0.33 then
					inst.components.talker:Say(STRINGS.MUSHA_TALK_FOOD_BAD_SORT[food.components.edible.foodtype])
				else
					inst.components.talker:Say(GetString(inst.prefab, "ANNOUNCE_HATEFOOD"))
				end
				inst.components.sanity:DoDelta(-20)
				if inst.components.health.currenthealth > 5 then
					inst.components.health:DoDelta(-3)
				end
			end
		)
		inst.components.hunger:DoDelta(food.components.edible.hungervalue * .25)
	elseif not string.find(tostring(food.prefab), "monster") and not string.find(tostring(food.prefab), "human") then
		-- basic taste
		if inst.musha_settings.princess_taste then
			if (food:HasTag("stale") or food:HasTag("spoiled")) and food.prefab ~= "butterflywings" then
				inst:DoTaskInTime(
					0.7,
					function()
						inst.sg:GoToState("refuseeat")
						inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_FOOD_OLD))
						inst.components.talker:Say(GetString(inst.prefab, "ANNOUNCE_HATEFOOD"))
					end
				)
			elseif food.prefab == "butterflywings" then
				inst:DoTaskInTime(
					0.5,
					function()
						inst.sg:GoToState("refuseeat")
						inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_FOOD_BUG))
						inst.components.talker:Say(GetString(inst.prefab, "ANNOUNCE_HATEFOOD"))
						inst.components.sanity:DoDelta(-10)
					end
				)
			end
		end
		inst.components.musha_fatiguesleep:DoDelta(-food.components.edible.healthvalue * 0.5)
		inst.components.musha_staminasleep:DoDelta(food.components.edible.hungervalue * 0.1)
		inst.components.musha_spellpower:DoDelta(food.components.edible.sanityvalue)
		inst:PushEvent(
			"musha_gainexp",
			food.components.edible.healthvalue * 0.07 + food.components.edible.hungervalue * 0.02 +
				food.components.edible.sanityvalue * 0.1
		)
	end

	if string.find(tostring(food.prefab), "monster") then
		if inst.musha_settings.princess_taste then
			inst:DoTaskInTime(
				0.7,
				function()
					inst.sg:GoToState("refuseeat")
					local random_chance = math.random()
					if random_chance < 0.25 then
						inst.components.talker:Say(STRINGS.MUSHA_TALK_FOOD_BAD_2)
					elseif random_chance < 0.5 then
						inst.components.talker:Say(STRINGS.MUSHA_TALK_FOOD_MONSTER_1)
					elseif random_chance < 0.75 then
						inst.components.talker:Say(STRINGS.MUSHA_TALK_FOOD_MONSTER_2)
					else
						inst.components.talker:Say(GetString(inst.prefab, "ANNOUNCE_HATEFOOD"))
					end
					inst.components.sanity:DoDelta(-5)
				end
			)
		end

		if math.random() < (inst.components.musha_skills.skill_point["Berserk"]:value() < 2 and 0.3 or 0.5) then
			inst.components.musha_skills:EnableBerserk()
		end
	end

	if string.find(tostring(food), "human") then
		if inst.musha_settings.princess_taste then
			inst:DoTaskInTime(
				1,
				function()
					inst.sg:GoToState("refuseeat")
					inst.components.sanity:DoDelta(-15)
				end
			)
		end
		inst.components.musha_skills:EnableBerserk()
	end
end

local function musha_taste(inst)
	if inst.components.hunger.current > 180 and inst.musha_settings.princess_taste then
		inst.components.eater:SetDiet({FOODGROUP.OMNI}, {FOODGROUP.BERRIES_AND_SEEDS})
		return
	end
	if inst.components.hunger:IsStarving() then
		if inst.musha_settings.edible_food_type == "meat" then
			inst.components.talker:Say(STRINGS.MUSHA_TALK_FOOD_ANY)
		end
		if inst.musha_settings.edible_food_type == "veggie" then
			inst.components.talker:Say(STRINGS.MUSHA_TALK_FOOD_ANY)
		end
		inst.components.eater:SetDiet(
			{FOODGROUP.OMNI},
			{FOODGROUP.OMNI},
			{FOODTYPE.MEAT, FOODTYPE.GOODIES},
			{FOODTYPE.VEGGIE, FOODTYPE.GOODIES}
		)
		return
	end

	if inst.musha_settings.edible_food_type == "normal" then
		inst.components.eater:SetDiet(
			{FOODGROUP.OMNI},
			{FOODGROUP.OMNI},
			{FOODTYPE.MEAT, FOODTYPE.GOODIES},
			{FOODTYPE.VEGGIE, FOODTYPE.GOODIES}
		)
	elseif inst.musha_settings.edible_food_type == "meat" then
		inst.components.eater:SetDiet({FOODGROUP.OMNI}, {FOODTYPE.MEAT, FOODTYPE.GOODIES})
	elseif inst.musha_settings.edible_food_type == "veggie" then
		inst.components.eater:SetDiet({FOODGROUP.OMNI}, {FOODTYPE.VEGGIE, FOODTYPE.GOODIES})
	end
end

local function treasure_recharge(inst)
	local treasure_multiple = inst.components.musha_skills.skill_point["Sniff"]:value() == 2 and 0.8 or 1
	if inst.components.musha_skills.data.treasure <= 100 then
		inst.components.musha_skills.data.treasure =
			math.min(
			inst.components.musha_skills.data.treasure +
				inst.musha_settings.treasure_recharge_multiple * (inst.components.musha_skills.currentlevel / 2) / treasure_multiple,
			100
		)
		if inst.components.musha_skills.data.treasure == 100 then
			inst.components.talker:Say(STRINGS.MUSHA_TALK_TREASURE_SMELL .. "\n[(X)]")
			inst.treasure_recharge_task:Cancel()
			inst.treasure_recharge_task = nil
		end
	end
end

local function OnTaskTick(inst)
	local musha_staminasleep = inst.components.musha_staminasleep:GetPercent()
	local musha_fatiguesleep = inst.components.musha_fatiguesleep:GetPercent()
	local hunger = inst.components.hunger:GetPercent()
	if not inst.components.musha_skills.berserk then
		inst.components.locomotor.groundspeedmultiplier =
			1.15 * (0.5 * musha_staminasleep + 0.3 * (1 - musha_fatiguesleep) + 0.2 * hunger)
	else
		inst.components.locomotor.groundspeedmultiplier = 1.15 * (0.35 * hunger + 0.65)
	end
end

local function fullmoontoday(inst, isday)
	if isday then
		inst.components.musha_skills:DisableBerserk()
		inst:StopWatchingWorldState("isday", fullmoontoday)
	end
end

local function tofullmoon(inst, isfullmoon)
	if isfullmoon then
		inst:WatchWorldState("isday", fullmoontoday)
		inst.components.musha_skills:EnableBerserk()
	end
end

local function oncurrentlevel(self)
	self.levelexp = self.currentlevel * 10 * self.inst.musha_settings.level_difficulty
	local health_percent = self.inst.components.health:GetPercent()
	local sanity_percent = self.inst.components.sanity:GetPercent()
	--TODO:血量脑力难度设置
	self.inst.components.health.maxhealth =
		math.min(75 + self.currentlevel * 5, 125 + math.ceil((self.currentlevel - 11) * 0.5) * 5)
	self.inst.components.sanity.max =
		math.min(75 + self.currentlevel * 5, 105 + math.ceil((self.currentlevel - 7) * 0.5) * 5)
	self.inst.components.health:SetPercent(health_percent)
	self.inst.components.sanity:SetPercent(sanity_percent)
end

local function oncurrentexp(self)
	local currentexp_new, currentlevel_new = self.currentexp, self.currentlevel
	while currentexp_new >= self.levelexp and currentlevel_new < self.maxlevel do
		currentexp_new = currentexp_new - self.levelexp
		currentlevel_new = currentlevel_new + 1
		self.levelexp = currentlevel_new * 10 * self.inst.musha_settings.level_difficulty
		print(currentexp_new, currentlevel_new, self.levelexp)
	end

	if currentlevel_new == self.maxlevel and currentexp_new > self.levelexp then
		currentexp_new = self.levelexp
	end

	if currentexp_new ~= self.currentexp or currentlevel_new ~= self.currentlevel then
		self.inst.components.talker:Say(
			string.format(
				STRINGS.MUSHA_LEVEL_LEVEL .. " %d\n" .. STRINGS.MUSHA_LEVEL_LEVEL_UP .. "+%d",
				currentlevel_new,
				currentlevel_new - self.currentlevel
			)
		)
		self.inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_finish", "snd")
		self.inst.SoundEmitter:PlaySound("dontstarve/wilson/equip_item_gold")
		self.skill_point["Unassigned"]:set(self.skill_point["Unassigned"]:value() + currentlevel_new - self.currentlevel)

		self.currentlevel = currentlevel_new
		self.currentexp = currentexp_new
	end
end

local Musha_Skills =
	Class(
	function(self, inst)
		inst:AddComponent("musha_spellpower")

		self.inst = inst

		self.levelexp = 0
		self.maxlevel = 30
		self.currentlevel = 1
		self.currentexp = 0
		self.data = {
			music = 0,
			treasure = 95
		}

		self.skill_point = self.inst.replica.musha_skills.skill_point
		self.skilldata = function(skillname, dataname)
			return MUSHA_SETTINGS.musha_skilldata[skillname][self.skill_point[skillname]:value()][dataname]
		end
		self.musha_skilldata = deepcopy(MUSHA_SETTINGS.musha_skilldata)

		self.first_treasure = true
		self.berserk = false

		self.inst:ListenForEvent("hungerdelta", musha_taste)
		self.inst:ListenForEvent(
			"musha_gainexp",
			function(inst, exp)
				local self = inst.components.musha_skills
				if self.currentlevel < self.maxlevel then
					self.currentexp = self.currentexp + (exp or 0)
				end
			end
		)
		--ThePlayer:PushEvent("musha_gainexp", 5000)
		self.inst:WatchWorldState("isfullmoon", tofullmoon)
		self.inst:ListenForEvent(
			"death",
			function(inst)
				self.DisableBerserk(true)
			end
		)
		self.inst:ListenForEvent(
			"gotosleep",
			function()
				local music_recharge_task = self.inst:DoPeriodicTask(1, music_recharge)
				local function stop_music_recharge_task()
					if music_recharge_task ~= nil then
						music_recharge_task:Cancel()
						music_recharge_task = nil
					end
				end
				self.inst:ListenForEvent("onwakeup", stop_music_recharge_task)
			end
		)

		if self.inst:HasTag("_musha") then
			self.inst.components.eater:SetOnEatFn(Expeat)
			local period = 1
			self.inst:DoPeriodicTask(period, OnTaskTick)
		end
	end,
	nil,
	{
		currentlevel = oncurrentlevel,
		currentexp = oncurrentexp
	}
)

function Musha_Skills:Updata(name, data)
	self.skill_point[name]:set(data)
	local Updata_Actions = {
		Valkyr = function()
			self:Valkyr()
		end,
		ElectricShield = function()
			if self.skill_point["FireShield"]:value() > 0 and not self.fireshieldtask then
				self:refreshfireshield()
			end
		end
	}
	if type(Updata_Actions[name]) == "function" then
		Updata_Actions[name]()
	end
end

function Musha_Skills:Sniff(inst)
	if self.skill_point["Sniff"]:value() == 0 then
		inst.components.talker:Say(STRINGS.MUSHA_SKILLS.SNIFF .. STRINGS.MUSHA_SKILLS.NOTLEARNED)
		return
	end
	if IsNearDanger(inst) then
		inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_SLEEP_DANGER))
	end
	local function musha_treasurehunt(inst)
		local offset
		if self.first_treasure then
			local pos = inst:GetPosition()
			offset = FindWalkableOffset(pos, math.random() * 2 * math.pi, math.random(5, 10), 10)
			if offset then --fixd compatibility
				local spawn_pos = pos + offset
				SpawnPrefab("musha_treasure_first").Transform:SetPosition(spawn_pos:Get())
				local puff = SpawnPrefab("small_puff")
				puff.Transform:SetPosition(spawn_pos:Get())
				local shovel = SpawnPrefab("shovel")
				shovel.Transform:SetPosition(spawn_pos:Get())
				inst:DoTaskInTime(
					0.5,
					function()
						inst.components.talker:Say(STRINGS.MUSHA_TALK_TREASURE_FIRST)
						inst:DoTaskInTime(
							2,
							function()
								inst.components.talker:Say(STRINGS.MUSHA_TALK_TREASURE_YAMCHE)
							end
						)
					end
				)
			end
			self.first_treasure = nil
		else
			local condition = math.random()
			local pos = inst:GetPosition()
			local guard, distance
			if condition < 0.4 then
				offset = FindWalkableOffset(pos, math.random() * 800 * math.pi, math.random(900, 1000), 500)
				guard = FindWalkableOffset(pos, math.random() * 1 * math.pi, math.random(1, 3), 1)
				distance = "FAR"
			elseif condition < 0.75 then
				offset = FindWalkableOffset(pos, math.random() * 800 * math.pi, math.random(900, 1000), 500)
				guard = FindWalkableOffset(pos, math.random() * 1 * math.pi, math.random(1, 3), 1)
				distance = "MED"
			else
				offset = FindWalkableOffset(pos, math.random() * 800 * math.pi, math.random(900, 1000), 500)
				guard = FindWalkableOffset(pos, math.random() * 1 * math.pi, math.random(1, 3), 1)
				distance = "NEAR"
			end
			inst:DoTaskInTime(
				1,
				function()
					inst.components.talker:Say(STRINGS.MUSHA_TALK_TREASURE[distance])
				end
			)
			local treasure1 = SpawnPrefab("musha_treasure")
			local spawn_pos = pos + offset
			treasure1.Transform:SetPosition(spawn_pos:Get())
			if math.random() < 0.5 and guard then
				local spawn_pos_gw = pos + offset + guard
				local gworm = SpawnPrefab("musha_greenworm")
				gworm.Transform:SetPosition(spawn_pos_gw:Get())
				gworm.sg:GoToState("lure_enter")
			end
			-- green fruit
			if math.random() < 0.5 and guard then
				local spawn_pos_gw = pos + offset + guard
				local gworm = SpawnPrefab("musha_appleplant")
				gworm.Transform:SetPosition(spawn_pos_gw:Get())
			end
			if math.random() < 0.25 and guard then
				local spawn_pos_gw = pos + offset + guard
				local gworm = SpawnPrefab("musha_appleplant")
				gworm.Transform:SetPosition(spawn_pos_gw:Get())
			end
		end
		if not offset then
			inst.components.talker:Say(STRINGS.MUSHA_TALK_TREASURE_FAILED)
			self.data.treasure = 100
			return
		else
			TheWorld.Musha_Watcher.all_treasure_count = TheWorld.Musha_Watcher.all_treasure_count + 1
			self.data.treasure = 0
			TheWorld.Musha_Watcher.all_treasure_count = TheWorld.Musha_Watcher.all_treasure_count + 1
			self:StartTreasureRecharge()
		end
	end
	if inst.components.health:IsDead() or inst:HasTag("playerghost") then
		return
	end
	if self.data.treasure < 100 then
		return
	end
	if inst.components.rider ~= nil and inst.components.rider:IsRiding() then
		inst.components.talker:Say(STRINGS.MUSHA_TALK_MUSIC_RIDE)
		return
	end
	if self.skill_point["Sniff"]:value() < 1 then
		inst.components.talker:Say(STRINGS.MUSHA_SKILLS.SNIFF .. STRINGS.MUSHA_SKILLS.NOTLEARNED)
		return
	end
	if inst.components.playercontroller then
		inst.components.playercontroller:Enable(false)

		--[[ if TheSim:FindFirstEntityWithTag("musha_treasure") then
        local treasures = TheSim:FindFirstEntityWithTag("musha_treasure")
        local x, y, z = treasures.Transform:GetWorldPosition()
        local minimap = TheWorld.minimap.MiniMap
        minimap:ShowArea(x, y, z, 20)
        end ]]
		inst.components.talker:Say(STRINGS.MUSHA_TALK_TREASURE_SNIFF)
		local item = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
		inst.sg:GoToState("talk")
		if item then
			inst.components.inventory:Unequip(EQUIPSLOTS.HANDS, true)
		--inst.components.inventory:GiveItem(item)
		end
		inst:DoTaskInTime(
			1.5,
			function()
				inst.components.playercontroller:Enable(false)
				inst.sg:GoToState("musha_peertelescope")
				inst.components.talker.colour = Vector3(1, 0.85, 0.7, 1)
				inst.components.talker:Say(STRINGS.MUSHA_TALK_TREASURE_FOUND)
				inst:DoTaskInTime(
					3,
					function()
						inst.components.playercontroller:Enable(false)
						inst.sg:GoToState("musha_map")
						inst.components.talker.colour = Vector3(1, 0.85, 0.7, 1)
						inst.components.talker:Say(STRINGS.MUSHA_TALK_TREASURE_MARK)
						inst:DoTaskInTime(
							3.5,
							function()
								inst.components.talker.colour = Vector3(1, 1, 1, 1)
								musha_treasurehunt(inst)
								inst.components.playercontroller:Enable(true)
								inst.components.inventory:Equip(item)
							end
						)
					end
				)
			end
		)
	end
end

function Musha_Skills:Sing(inst)
	if self.skill_point["Sing"]:value() == 0 then
		inst.components.talker:Say(STRINGS.MUSHA_SKILLS.MUSIC .. STRINGS.MUSHA_SKILLS.NOTLEARNED)
		return
	end
	local function DoPlantBloom(inst)
		local BLOOM_CHOICES = {
			["musha_bulb"] = 0.22,
			["musha_bulb_double"] = 0.05,
			["musha_berry"] = 0.03,
			["musha_fern"] = 3,
			["light_fern"] = 0.6,
			["green_fern"] = 5.2
		}
		local x, y, z = inst.Transform:GetWorldPosition()
		local map = TheWorld.Map
		local offset =
			FindValidPositionByFan(
			math.random() * 1 * PI,
			math.random() * 2,
			4,
			function(offset)
				local x1 = x + offset.x
				local z1 = z + offset.z
				return map:IsPassableAtPoint(x1, 0, z1) and map:IsDeployPointClear(Vector3(x1, 0, z1), nil, 1) and
					#TheSim:FindEntities(x1, 0, z1, 2.5, {"stalkerbloom"}) < 4
			end
		)

		if offset ~= nil then
		--SpawnPrefab(weighted_random_choice(BLOOM_CHOICES)).Transform:SetPosition(x + offset.x, 0, z + offset.z)
		end
	end
	if inst.components.health:IsDead() or inst:HasTag("playerghost") then
		inst.components.talker:Say(STRINGS.MUSHA_TALK_GHOST_MUSIC)
		return
	end
	if inst.components.rider ~= nil and inst.components.rider:IsRiding() then
		inst.components.talker:Say(STRINGS.MUSHA_TALK_MUSIC_RIDE)
		return
	end
	if self.data.music < 100 then
		inst.components.talker:Say(STRINGS.MUSHA_TALK_NEED_SLEEP)
		return
	end
	self.data.music = self.data.music * 0
	local type = math.random(3)
	inst.components.talker:Say(STRINGS.MUSHA_TALK_MUSIC_TYPE .. type)
	if inst.components.playercontroller then
		local lightorb = SpawnPrefab("musha_spore2")
		inst.components.playercontroller:Enable(false)
		inst.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
		inst.sg:GoToState("play_flute2")
		inst.SoundEmitter:PlaySound("dontstarve/wilson/onemanband")
		inst.Light:SetRadius(0.5)
		inst.Light:SetFalloff(.75)
		inst.Light:SetIntensity(.1)
		inst.Light:SetColour(90 / 255, 90 / 255, 90 / 255)
		inst.components.health:SetInvincible(true)
		inst.components.sanityaura.aura = TUNING.SANITYAURA_HUGE * 5
		inst:DoTaskInTime(
			3,
			function()
				inst.SoundEmitter:PlaySound("dontstarve/wilson/onemanband")
				inst.sg:GoToState("play_flute2")
			end
		)
		inst:DoTaskInTime(
			6,
			function()
				inst.sg:GoToState("enter_onemanband")
			end
		)
		inst:DoTaskInTime(
			9,
			function()
				inst.SoundEmitter:PlaySound("dontstarve/wilson/onemanband")
				inst.sg:GoToState("play_flute2")
			end
		)
		inst:DoTaskInTime(
			12,
			function()
				inst.components.playercontroller:Enable(true)
				inst.AnimState:SetBloomEffectHandle("")
				inst.Light:Enable(true) --[[inst.components.talker:Say("[Light Aura] -ON     \n- Sanity Regen UP    \n- Sleep/Tired Regen UP")]]
				lightorb.Transform:SetPosition(inst:GetPosition():Get())
				lightorb.components.follower:SetLeader(inst)
				inst.sg:GoToState("play_horn2")
				if type == 1 then
					--hounds.components.follower:SetLeader(inst)
					local hounds = SpawnPrefab("musha_ghosthound")
					hounds.Transform:SetPosition(inst:GetPosition():Get())
					hounds.Transform:SetPosition(inst:GetPosition():Get())
					hounds.followdog = true
				elseif type == 2 then
					local shadows = SpawnPrefab("musha_shadow")
					SpawnPrefab("statue_transition_2").Transform:SetPosition(inst:GetPosition():Get())
					shadows.Transform:SetPosition(inst:GetPosition():Get())
					shadows.followdog = true
				elseif type == 3 then
					local drakeangle = math.random(1, 360)
					local x, y, z = inst.Transform:GetWorldPosition()
					local function set_musha_tentacle_frost(inst)
						local offset = FindWalkableOffset(inst:GetPosition(), drakeangle * DEGREES, math.random(2, 8), 30, false, false)
						local musha_tentacle_frost = SpawnPrefab("musha_tentacle_frost")
						musha_tentacle_frost.Transform:SetPosition(x + offset.x, y + offset.y, z + offset.z)
						musha_tentacle_frost.SoundEmitter:PlaySound("dontstarve/common/gem_shatter")
						musha_tentacle_frost.components.follower:SetLeader(inst)
						SpawnPrefab("statue_transition").Transform:SetPosition(x + offset.x, y + offset.y, z + offset.z)
					end
					inst:DoTaskInTime(0, set_musha_tentacle_frost)
					inst:DoTaskInTime(3, set_musha_tentacle_frost)
					inst:DoTaskInTime(6, set_musha_tentacle_frost)
					inst:DoTaskInTime(9, set_musha_tentacle_frost)
					inst:DoTaskInTime(12, set_musha_tentacle_frost)
					inst:DoTaskInTime(15, set_musha_tentacle_frost)
				end
				inst.components.sanityaura.aura = TUNING.SANITYAURA_HUGE
				inst.components.health:SetInvincible(false)

				local recovery =
					inst.DoPeriodicTask(
					3,
					function()
						inst.components.sanity:DoDelta(3)
						inst.components.musha_spellpower:DoDelta(2.5)
						DoPlantBloom(inst)
					end
				)
				inst:DoTaskInTime(
					180,
					function()
						recovery:Cancel()
						inst.SoundEmitter:PlaySound("dontstarve/common/fireOut")
						SpawnPrefab("statue_transition_2").Transform:SetPosition(inst:GetPosition():Get())
						inst.components.sanityaura.aura = 0
						inst.Light:SetRadius(0.5)
						inst:DoTaskInTime(
							5,
							function()
								inst.Light:Enable(false)
								inst.SoundEmitter:PlaySound("dontstarve/common/fireOut")
							end
						)
					end
				)
			end
		)
	end
end

function Musha_Skills:Level_Info(inst)
	inst.components.talker:Say(
		"[" ..
			STRINGS.MUSHA_LEVEL_LEVEL ..
				"]: " ..
					self.currentlevel ..
						" " ..
							STRINGS.MUSHA_LEVEL_EXP ..
								" " ..
									math.floor(self.currentexp) ..
										"/" ..
											self.levelexp ..
												"\n[" ..
													(inst.components.musha_staminasleep and inst.components.musha_fatiguesleep and
														(STRINGS.MUSHA_LEVEL_SLEEP ..
															"]: " ..
																math.ceil(inst.components.musha_staminasleep:GetPercent() * 100) ..
																	"%  [" ..
																		STRINGS.MUSHA_LEVEL_TIRED ..
																			"]: " .. math.ceil(inst.components.musha_fatiguesleep:GetPercent() * 100) .. "%\n[")) ..
														STRINGS.MUSHA_LEVEL_MUSIC ..
															"]: " ..
																math.floor(self.data.music) ..
																	"%   [" .. STRINGS.MUSHA_LEVEL_SNIFF .. "]: " .. math.floor(self.data.treasure) .. "%"
	)
end

function Musha_Skills:GoAwake(inst)
	--inst:ShowHUD(true)
	inst:RemoveTag("sleeping")
	inst:PushEvent("onwakeup")
	--#TODO:音乐填充硬直
	--inst.components.playercontroller:Enable(false)
	inst.sg:GoToState("wakeup")
	inst.Light:SetRadius(1)
	inst.Light:SetFalloff(.8)
	inst.Light:SetIntensity(.8)
	inst.Light:SetColour(150 / 255, 150 / 255, 150 / 255)
	inst.Light:Enable(true)
	if self.data.music < 100 then
		inst:DoTaskInTime(
			1.75,
			function()
				inst.Light:Enable(false)
				inst.AnimState:PushAnimation(RandomChoice({"mime1", "mime4", "mime3"}), false)
			end
		)
	else
		inst.AnimState:SetBloomEffectHandle("")
		inst:DoTaskInTime(
			2,
			function()
				inst.components.talker:Say(STRINGS.MUSHA_TALK_MUSIC_READY)
				inst.sg:GoToState("play_flute2")
				inst.Light:Enable(false)
				inst.AnimState:SetBloomEffectHandle("")
				inst.SoundEmitter:PlaySound("dontstarve/wilson/onemanband")
				inst.components.playercontroller:Enable(true)
			end
		)
	end
end

function Musha_Skills:AttackWakeFn(inst, data)
	if data and data.attacker and inst:HasTag("sleeping") and data.attacker.components.combat then
		inst.sg:GoToState("wakeup")
		self:GoAwake(inst)
	end
end

function Musha_Skills:GoSleep(inst)
	--inst:ShowHUD(false)
	if TheWorld.state.temperature < 10 then
		inst.AnimState:OverrideSymbol("swap_bedroll", "swap_bedroll_furry", "bedroll_furry")
	else
		inst.AnimState:OverrideSymbol("swap_bedroll", "swap_bedroll_straw", "bedroll_straw")
	end
	inst.sg:GoToState("knockout")
	inst:AddTag("sleeping")
	inst:PushEvent("gotosleep")
	if inst:HasTag("Musha_ShadowHide") then
		local fx = SpawnPrefab("statue_transition_2")
		fx.entity:SetParent(inst.entity)
		fx.Transform:SetScale(1.2, 1.2, 1.2)
		fx.Transform:SetPosition(0, 0, 0.5)
		inst.components.sanity:DoDelta(self.skilldata("ShadowHide", "sanity_need"))
		self.ExitShadow(inst)
	end
	inst.sg:AddStateTag("busy")
	inst:ListenForEvent("attacked", self.AttackWakeFn)
	inst.components.musha_skills:DisableBerserk(true)
end

function Musha_Skills:Sleep_Check(inst)
	if not inst.LightWatcher:IsInLight() then
		inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_SLEEP_NEED_LIGHT))
		return false
	end
	if IsNearDanger(inst) then
		inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_SLEEP_DANGER))
		return false
	end
	return true
end

function Musha_Skills:Sleep_Switch(inst)
	if self.skill_point["Sleep"]:value() < 1 then
		inst.components.talker:Say(STRINGS.MUSHA_SKILLS.SLEEP .. STRINGS.MUSHA_SKILLS.NOTLEARNED)
		return
	end
	if not inst:HasTag("sleeping") then
		if
			not inst.components.health:IsDead() and not (inst.sg:HasStateTag("moving") or inst.sg:HasStateTag("attack")) and
				inst.components.musha_staminasleep
		 then
			if inst.components.musha_staminasleep.current >= 90 then
				if TheWorld.state.isday and inst.musha_settings.princess_sleep then
					inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_SLEEP_NO))
				elseif self:Sleep_Check(inst) then
					inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_SLEEP_GOOD))
					self:GoSleep(inst)
				end
			elseif self:Sleep_Check(inst) then
				if inst.components.musha_staminasleep.current >= 40 then
					inst.components.talker:Say(STRINGS.MUSHA_TALK_SLEEP_DIZZY_1)
				elseif inst.components.musha_staminasleep.current >= 25 then
					inst.components.talker:Say(STRINGS.MUSHA_TALK_SLEEP_DIZZY_2)
				elseif inst.components.musha_staminasleep.current >= 5 then
					inst.components.talker:Say(STRINGS.MUSHA_TALK_SLEEP_DIZZY_3)
				else
					inst.components.talker:Say(STRINGS.MUSHA_TALK_SLEEP_DIZZY_4)
				end
			end
		end
	else
		self:GoAwake(inst)
	end
	if inst.components.health:IsDead() or inst:HasTag("playerghost") then
		inst.components.talker:Say(STRINGS.MUSHA_TALK_GHOST_OOOOH)
	end
end

function Musha_Skills.ExitShadow(inst)
	local self = inst.components.musha_skills
	if self.ShadowInTask ~= nil then
		self.ShadowInTask:Cancel()
		self.ShadowInTask = nil
	end
	inst:AddTag("scarytoprey")
	inst:Show()
	inst.DynamicShadow:Enable(true)
	inst.components.colourtweener:StartTween({1, 1, 1, 1}, 0)
	inst:RemoveTag("Musha_ShadowHide")
	inst:RemoveTag("notarget")
	inst:RemoveEventCallback("onhitother", self.ExitShadow)
	inst:RemoveEventCallback("onhitother", self.ShadowAttack)
	inst:RemoveEventCallback("attacked", self.ShadowDiscovered)
end

function Musha_Skills.ShadowAttack(inst, data)
	local self = inst.components.musha_skills
	local target = data.target
	if not target:HasTag("smashable") and not target:HasTag("shadowminion") and not target:HasTag("alignwall") then
		if
			(target:HasTag("no_target") or target:HasTag("structure") or target:HasTag("wall") or
				target:HasTag("pillarretracting") or
				target:HasTag("tentacle_pillar") or
				target:HasTag("arm") or
				target:HasTag("shadow")) and
				not target.components.locomotor
		 then
			inst.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_NO_TARGET)
		elseif
			not (target:HasTag("no_target") or target:HasTag("structure") or target:HasTag("wall") or
				target:HasTag("pillarretracting") or
				target:HasTag("tentacle_pillar") or
				target:HasTag("arm") or
				target:HasTag("shadow")) and target.components.locomotor
		 then
			if
				not target.sg:HasStateTag("attack") and not target.sg:HasStateTag("shield") and not target.sg:HasStateTag("moving") and
					not target.sg:HasStateTag("frozen")
			 then
				inst.components.sanity:DoDelta(self.skilldata("ShadowHide", "sanity_need"))

				inst.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_SUCCESS)
				target.components.health:DoDelta(-self.skilldata("ShadowHide", "damage"))
				local dark1 = SpawnPrefab("statue_transition")
				local pos = Vector3(target.Transform:GetWorldPosition())
				dark1.Transform:SetPosition(pos:Get())
				dark1.Transform:SetScale(0.5, 4, 0.5)
				local fx = SpawnPrefab("explode_small")
				local pos = Vector3(target.Transform:GetWorldPosition())
				fx.Transform:SetPosition(pos:Get())
				self.ExitShadow(inst)
			elseif target.sg:HasStateTag("frozen") then
				inst.components.sanity:DoDelta(self.skilldata("ShadowHide", "sanity_need"))
				inst.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_SUCCESS .. "\n" .. STRINGS.MUSHA_TALK_SHADOWHIDE_FROZEN)
				target.components.health:DoDelta(-self.skilldata("ShadowHide", "damage") * 0.5)
				local dark1 = SpawnPrefab("statue_transition")
				local pos = Vector3(target.Transform:GetWorldPosition())
				dark1.Transform:SetPosition(pos:Get())
				dark1.Transform:SetScale(0.5, 4, 0.5)
				local fx = SpawnPrefab("explode_small")
				local pos = Vector3(target.Transform:GetWorldPosition())
				fx.Transform:SetPosition(pos:Get())
				self.ExitShadow(inst)
			elseif
				target.sg:HasStateTag("attack") or target.sg:HasStateTag("shield") or
					target.sg:HasStateTag("moving") and not target.sg:HasStateTag("frozen")
			 then
				inst.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_FAILED)
				local fx = SpawnPrefab("splash")
				local pos = Vector3(target.Transform:GetWorldPosition())
				fx.Transform:SetPosition(pos:Get())
				self.ExitShadow(inst)
			end
		end
	end
end

function Musha_Skills.ShadowDiscovered(inst, data)
	local self = inst.components.musha_skills
	local fx = SpawnPrefab("statue_transition_2")
	fx.entity:SetParent(inst.entity)
	fx.Transform:SetScale(1.2, 1.2, 1.2)
	fx.Transform:SetPosition(0, 0, 0.5)
	inst.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_ATTACKED)
	self.ExitShadow(inst)
end

function Musha_Skills.HideIn(inst)
	local self = inst.components.musha_skills
	if inst.musha_settings.shadowhide_real and TheNet:GetServerIsDedicated() then
		inst:Hide()
		inst.DynamicShadow:Enable(false)
		inst.replica.musha_skills.musha_shadowhide:set(not inst.replica.musha_skills.musha_shadowhide:value())
	else
		inst.components.colourtweener:StartTween({0.1, 0.1, 0.1, 1}, 0)
	end
	--inst._parent.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_HIDE_OTHER)
	inst.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_HIDE)
	local fx = SpawnPrefab("musha_shadowshield")
	fx.Transform:SetScale(0.5, 0.5, 0.5)
	fx.Transform:SetPosition(inst:GetPosition():Get())
	if not inst:HasTag("notarget") then
		inst:AddTag("notarget")
	end
	inst:RemoveTag("scarytoprey")
	SpawnPrefab("statue_transition").Transform:SetPosition(inst:GetPosition():Get())
	inst:RemoveEventCallback("onhitother", self.ExitShadow)
	inst:ListenForEvent("onhitother", self.ShadowAttack)
end

function Musha_Skills:ShadowHide(inst) --#TODO: PVP隐身
	if self.skill_point["ShadowHide"]:value() == 0 then
		inst.components.talker:Say(STRINGS.MUSHA_SKILLS.SHADOWHIDE .. STRINGS.MUSHA_SKILLS.NOTLEARNED)
		if inst.components.rider ~= nil and inst.components.rider:IsRiding() then
			inst.sg:GoToState("repelled")
		else
			inst.sg:GoToState("mindcontrolled")
		end
	else
		if not inst:HasTag("Musha_ShadowHide") then
			inst.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_PRE)
			inst:AddTag("Musha_ShadowHide")
			if
				(inst.components.sanity.current >= self.skilldata("ShadowHide", "sanity_need") and
					inst.components.musha_staminasleep and
					inst.components.musha_staminasleep.current >= 30) or
					inst.components.sanity.current >= self.skilldata("ShadowHide", "sanity_need") + 30
			 then
				inst.components.sanity:DoDelta(-self.skilldata("ShadowHide", "sanity_need"))
				inst.components.colourtweener:StartTween({0.3, 0.3, 0.3, 1}, 0)
				local fx = SpawnPrefab("statue_transition_2")
				fx.entity:SetParent(inst.entity)
				fx.Transform:SetScale(1.2, 1.2, 1.2)
				fx.Transform:SetPosition(0, 0, 0.5)
				self.ShadowInTask = inst:DoTaskInTime(self.skilldata("ShadowHide", "prepare_time"), self.HideIn)
				inst:ListenForEvent("onhitother", self.ExitShadow)
				inst:ListenForEvent("attacked", self.ShadowDiscovered)
			end
		else
			--inst._parent.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_SHOW_OTHER)
			inst.components.talker:Say(STRINGS.MUSHA_TALK_SHADOWHIDE_UNHIDE)

			local fx = SpawnPrefab("statue_transition_2")
			fx.entity:SetParent(inst.entity)
			fx.Transform:SetScale(1.2, 1.2, 1.2)
			fx.Transform:SetPosition(0, 0, 0.5)
			inst.components.sanity:DoDelta(self.skilldata("ShadowHide", "sanity_need"))
			self.ExitShadow(inst)
		end
	end
end

function Musha_Skills:StartTreasureRecharge()
	if self.inst.treasure_recharge_task ~= nil then
		self.inst.treasure_recharge_task:Cancel()
		self.inst.treasure_recharge_task = nil
	end
	if self.skill_point["Sniff"]:value() > 0 then
		self.inst.treasure_recharge_task = self.inst:DoPeriodicTask(5, treasure_recharge)
	end
end
--1睡觉，2嗅觉，3音乐，4隐身，5电击，6电盾，7重击，8女武神状态，9狂暴状态

-- --TODO:删除？
-- function Musha_Skills:ActiveSkills()
-- 	--Debug

-- 	self.treasure_multiple = self.skill_point["Sniff"]:value() == 2 and 0.8 or 1
-- 	self.music_multiple = self.skill_point["Music"]:value() == 2 and 0.65 or 1

-- 	self:StartTreasureRecharge()

-- 	if self.skill_point["ElectricAttack"]:value() > 0 then
-- 		local enable = self.electriceattack and self.musha_skilldata.ElectricAttack.enable or false
-- 		self.electriceattack = self.electriceattacklist[self.skill_point["ElectricAttack"]:value()]
-- 		self.musha_skilldata.ElectricAttack.enable = enable

-- 		local enable = self.poisonattack and self.musha_skilldata.ElectricAttack.enable or false
-- 		self.poisonattack = self.poisonattacklist[self.skill_point["ElectricAttack"]:value()]
-- 		self.musha_skilldata.ElectricAttack.enable = enable
-- 	end
-- 	if self.skill_point["PowerAttack"]:value() > 0 then
-- 		self.PowerAttack = self.PowerAttacklist[self.skill_point["PowerAttack"]:value()]
-- 	end
-- 	if self.skill_point[8] > 0 then
-- 		self.skilldata("Valkyr","damage")
-- 		self.skilldata("Valkyr","avoidance")
-- 	end

-- 	self:Valkyr()

-- 	if self.skill_point["Berserk"]:value() > 0 then
-- 		self.skilldata("Berserk", "damage") = self.berserdamagelist[self.skill_point["Berserk"]:value()]
-- 	end

-- 	if self.skill_point["FireShield"]:value() > 0 then
-- 		self.electriceshield = self.electriceshieldlist[self.skill_point["FireShield"]:value()]
-- 		local enable = self.fireshield and self.musha_skilldata.FireShield.enable or false
-- 		self.fireshield = self.fireshieldlist[self.skill_point["FireShield"]:value()]
-- 		self.musha_skilldata.FireShield.enable = enable
-- 		if not self.fireshieldtask then
-- 			self:refreshfireshield()
-- 		end
-- 	end
-- end

function Musha_Skills:refreshfireshield()
	if
		self.musha_skilldata.FireShield.enable or
			(self.inst.components.health and self.inst.components.health:IsDead() or self.inst:HasTag("playerghost"))
	 then
		return
	end

	self.musha_skilldata.FireShield.enable = true
	self.inst.components.talker:Say(STRINGS.MUSHA_SKILLS.FIRESHIELD .. " " .. STRINGS.MUSHA_SKILLS.READY)
	self.inst.components.health:SetAbsorptionAmount(
		self.skilldata("Valkyr", "avoidance") + self.skilldata("FireShield", "avoidance") +
			self.skilldata("Valkyr", "avoidance") * self.skilldata("FireShield", "avoidance")
	)

	if self.fireshieldtask ~= nil then
		self.fireshieldtask:Cancel()
	end
	self.fireshieldtask =
		self.inst:DoTaskInTime(
		self.skilldata("FireShield", "cooldowntime"),
		function(inst)
			self:refreshfireshield()
		end
	)

	self.inst:ListenForEvent(
		"attacked",
		function()
			self.musha_skilldata.FireShield.enable = false
			self.inst.components.health:SetAbsorptionAmount(self.skilldata("Valkyr", "avoidance"))
		end
	)
end

function Musha_Skills:Valkyr()
	self.inst.components.combat.damagemultiplier = self.inst.musha_settings.damage * self.skilldata("Valkyr", "damage")
	self.inst.components.health:SetAbsorptionAmount(self.skilldata("Valkyr", "avoidance"))
end

function Musha_Skills:OnSave()
	local data = {
		skill_point = {},
		data = self.data,
		currentlevel = self.currentlevel,
		currentexp = self.currentexp,
		first_treasure = self.first_treasure,
		berserk_duration = self.berserk_timer and self.berserk_timer - GetTime(),
		shadowhide = self.inst:HasTag("Musha_ShadowHide")
	}

	for k, v in pairs(self.skill_point) do
		TheWorld.Musha_Watcher.playerdata[self.inst.userid].skills[k] = v:value()
		data.skill_point[k] = v:value()
	end
	return data
end

function Musha_Skills:OnLoad(data)
	if data ~= nil then
		for k, v in pairs(data.skill_point) do
			self.skill_point[k]:set(v)
		end
		self.currentlevel = data.currentlevel
		self.currentexp = data.currentexp
		self.first_treasure = data.first_treasure
		if data.berserk_duration then
			self.inst:DoTaskInTime(
				0,
				function()
					self:EnableBerserk(data.berserk_duration)
				end
			)
		end
		if data.shadowhide then
			self.HideIn(self.inst)
		end
	end
end

function Musha_Skills:EnableBerserk(berserk_duration)
	if self.skill_point["Berserk"]:value() == 0 then
		return
	end
	if not self.berserk then
		berserk_duration = berserk_duration or 240
		self.inst.components.sanity.dapperness = TUNING.DAPPERNESS_SUPERHUGE
		self.berserk = true
		self.inst.components.talker:Say(STRINGS.MUSHA_TALK_BERSERK)
		self.berserk_timer = GetTime() + berserk_duration
		self.inst:DoTaskInTime(
			berserk_duration,
			function()
				self.berserk_timer = nil
				self:DisableBerserk()
			end
		)
		SpawnPrefab("statue_transition").Transform:SetPosition(self.inst:GetPosition():Get())
		SpawnPrefab("statue_transition_2").Transform:SetPosition(self.inst:GetPosition():Get())
		self.inst.AnimState:SetBuild("musha_body_white")
		self.inst.components.hunger.burnratemodifiers:SetModifier(self.inst, 1.35)
		self.inst.components.combat:SetAreaDamage(
			2,
			self.inst.musha_settings.range_damage * self.skilldata("Berserk", "damage")
		)
		musha_print(
			self.inst.musha_settings.range_damage,
			self.skilldata("Berserk", "damage"),
			self.inst.musha_settings.range_damage * self.skilldata("Berserk", "damage")
		)
	end
end

function Musha_Skills:DisableBerserk(force)
	if self.skill_point["Berserk"]:value() == 0 then
		return
	end
	if TheWorld.state.isfullmoon or self.berserk_timer and not force then
		return
	end
	if self.berserk then
		self.berserk = false
		self.inst.components.sanity.dapperness = 0
		self.inst.components.combat:SetAreaDamage(0, 0)
		self.inst.components.hunger.burnratemodifiers:SetModifier(self.inst, 1)
		SpawnPrefab("statue_transition").Transform:SetPosition(self.inst:GetPosition():Get())
		SpawnPrefab("statue_transition_2").Transform:SetPosition(self.inst:GetPosition():Get())
	end
end

function Musha_Skills.Musha_PoisonAttack(inst, data)
	local self = inst.components.musha_skills
	local target = data.target
	if target.poison_debuff_task == nil then
		target.components.locomotor.groundspeedmultiplier = 0.3
		SpawnPrefab("musha_spin_fx").entity:AddFollower():FollowSymbol(target.GUID, "body", 0, -200, 0.5)
		target.poison_debuff =
			target:DoPeriodicTask(
			0.5,
			function(target)
				target.components.health:DoDelta(-self.skilldata("PoisonAttack", "damage"))
			end
		)
		target.poison_debuff_task =
			target:DoTaskInTime(
			3,
			function(target)
				target.poison_debuff:Cancel()
				target.poison_debuff = nil
				target.components.locomotor.groundspeedmultiplier = 1
			end
		)
	else
		target.poison_debuff_task:Cancel()
		target.poison_debuff_task =
			target:DoTaskInTime(
			3,
			function(target)
				target.poison_debuff:Cancel()
				target.poison_debuff = nil
				target.components.locomotor.groundspeedmultiplier = 1
			end
		)
	end
end

function Musha_Skills:PoisonAttackSwitch(inst)
	if not self.musha_skilldata.ElectricAttack.enable then
		if inst.components.musha_spellpower:CanCost(self.skilldata("PoisonAttack", "spellpowercost")) then
			self.musha_skilldata.ElectricAttack.enable = true
			inst.components.talker.Say(STRINGS.MUSHA_TALK_READY_POISON)
			inst:ListenForEvent("onhitother", self.Musha_PoisonAttack)
		else
			inst.components.talker:Say(STRINGS.MUSHA_TALK_NEED_SPELLPOWER)
		end
	else
		inst.components.talker:Say(STRINGS.MUSHA_TALK_CANCEL_POISON)
		inst:RemoveEventCallback("onhitother", self.Musha_PoisonAttack)
		self.musha_skilldata.ElectricAttack.enable = false
	end
end

local function ActiveElectricAttack(inst)
	inst.Light:SetRadius(1)
	inst.Light:SetFalloff(.8)
	inst.Light:SetIntensity(.8)
	inst.Light:SetColour(150 / 255, 150 / 255, 150 / 255)
	inst.Light:Enable(true)
	inst:DoTaskInTime(
		1,
		function(inst)
			inst.Light:Enable(false)
		end
	)
	inst.components.combat:SetRange(12, 12)
	inst.SoundEmitter:PlaySound("dontstarve/maxwell/shadowmax_appear")
	inst:ListenForEvent("onhitother", inst.components.musha_skills.ElectricAttack)
end

function Musha_Skills.ElectricAttack(inst, data)
	local self = inst.components.musha_skills
	local target = data.target
	if not self.musha_skilldata.ElectricAttack.cooldown then
		if inst.musha_settings.lightning_sound then
			SpawnPrefab("lightning").Transform:SetPosition(target:GetPosition():Get())
		else
			SpawnPrefab("musha_lightning").Transform:SetPosition(target:GetPosition():Get())
		end
		SpawnPrefab("shock_fx").Transform:SetPosition(target:GetPosition():Get())
		local fx = SpawnPrefab("firering_fx")
		fx.Transform:SetScale(0.6, 0.6, 0.6)
		fx.Transform:SetPosition(target:GetPosition():Get())
		target.components.health:DoDelta(-self.skilldata("ElectricAttack", "damage"))
		inst.components.combat:SetRange(2)
		inst.AnimState:SetBloomEffectHandle("")
		if inst.components.musha_equipbuff.buff == "frost" and target.components.freezable then
			target.components.freezable:AddColdness(2)
			target.components.health:DoDelta(-20)
		elseif inst.components.musha_equipbuff.buff == "fire" and target.components.burnable then
			target.components.burnable:Ignite()
			target.components.health:DoDelta(-60)
			target:DoTaskInTime(
				0.5,
				function(target)
					target.components.burnable:Extinguish()
				end
			)
		end
		self.musha_skilldata.ElectricAttack.cooldown = true
		inst:RemoveEventCallback("onhitother", self.ElectricAttack)
		inst:DoTaskInTime(
			self.skilldata("ElectricAttack", "cooldowntime"),
			function()
				self.musha_skilldata.ElectricAttack.cooldown = false
				if self.musha_skilldata.ElectricAttack.enable then
					if inst:HasTag("Musha_ShadowHide") then
						self:ElectricAttackSwitch(inst)
						self:PoisonAttackSwitch(inst)
					else
						if inst.components.musha_spellpower:CanCost(self.skilldata("ElectricAttack", "spellpowercost")) then
							ActiveElectricAttack()
						else
							self.waitingforelectricattack =
								inst:DoPeriodicTask(
								0.1,
								function(inst)
									if inst.components.musha_spellpower:CanCost(self.skilldata("ElectricAttack", "spellpowercost")) then
										ActiveElectricAttack()
										self.waitingforelectricattack:Cancel()
										self.waitingforelectricattack = nil
									end
								end
							)
						end
					end
				end
			end
		)
	end
end

function Musha_Skills:ElectricAttackSwitch(inst)
	if not inst.components.health:IsDead() and not inst:HasTag("playerghost") then
		if self.skill_point["ElectricAttack"]:value() == 0 then
			inst.components.talker:Say(STRINGS.MUSHA_SKILLS.ELECTRICATTACK .. STRINGS.MUSHA_SKILLS.NOTLEARNED)
			return
		end

		if self.musha_skilldata.ElectricAttack.enable then
			self.musha_skilldata.ElectricAttack.enable = false
			inst.AnimState:SetBuild("musha")
			inst.components.combat:SetRange(2)
			if not self.musha_skilldata.ElectricAttack.cooldown then
				inst.components.musha_spellpower:DoDelta(self.skilldata("ElectricAttack", "spellpowercost"))
			end
			if self.waitingforelectricattack then
				self.waitingforelectricattack:Cancel()
				self.waitingforelectricattack = nil
			end
			inst:RemoveEventCallback("onhitother", self.ElectricAttack)
		else
			if inst.components.musha_spellpower:CanCost(self.skilldata("ElectricAttack", "spellpowercost")) then
				inst.components.talker:Say(
					STRINGS.MUSHA_SKILLS.ELECTRICATTACK .. "Lv:" .. self.skill_point["ElectricAttack"]:value()
				)
				ActiveElectricAttack(inst)
			end
		end
	end
end

function Musha_Skills:SpecialAttackSwitch(inst)
	if inst:HasTag("Musha_ShadowHide") then
		self:PoisonAttackSwitch(inst)
	else
		self:ElectricAttackSwitch(inst)
	end
end

function Musha_Skills:ElectricShield(inst)
	if not inst.components.health:IsDead() and not inst:HasTag("playerghost") then
		if self.skill_point["ElectricShield"]:value() == 0 then
			inst.components.talker:Say(STRINGS.MUSHA_SKILLS.ELECTRICSHIELD .. STRINGS.MUSHA_SKILLS.NOTLEARNED)
			return
		end
		if self.musha_skilldata.ElectricShield.cooldown then
			inst.components.talker:Say(STRINGS.MUSHA_SKILLS.ELECTRICSHIELD .. STRINGS.MUSHA_SKILLS.COOLDOWN)
		else
			self.musha_skilldata.ElectricShield.cooldown = true
			if inst.components.musha_spellpower and inst.components.musha_spellpower:CanCost(30) then
				inst.components.health:SetInvincible(true)
				local fx = SpawnPrefab("musha_forcefieldx")
				inst.SoundEmitter:PlaySound("dontstarve/creatures/chester/raise")
				inst.SoundEmitter:PlaySound("dontstarve/creatures/chester/pop")
				fx.entity:SetParent(inst.entity)
				if inst.components.rider ~= nil and inst.components.rider:IsRiding() then
					fx.Transform:SetScale(2, 2, 2)
				else
					fx.Transform:SetScale(0.8, 0.8, 0.8)
				end
				fx.Transform:SetPosition(0, 0.2, 0)
				local fx_hitanim = function()
					fx.AnimState:PlayAnimation("hit")
					fx.AnimState:PushAnimation("idle_loop")
				end
				fx:ListenForEvent("blocked", fx_hitanim, inst)

				inst:DoTaskInTime(
					self.skilldata("ElectricShield", "duration"),
					function()
						fx:RemoveEventCallback("blocked", fx_hitanim, inst)
						if inst:IsValid() then
							fx.kill_fx(fx)
						end
						inst.components.health:SetInvincible(false)
						if self.skill_point["FireShield"]:value() == 5 then
							self:refreshfireshield()
						end
					end
				)
				inst:DoTaskInTime(
					self.skilldata("ElectricShield", "cooldowntime"),
					function()
						self.musha_skilldata.ElectricShield.cooldown = false
						inst.components.talker:Say(STRINGS.MUSHA_SKILLS.ELECTRICSHIELD .. " " .. STRINGS.MUSHA_SKILLS.READY)
						SpawnPrefab("sparks").Transform:SetPosition(inst:GetPosition():Get())
						inst.SoundEmitter:PlaySound("dontstarve/characters/wx78/spark")
					end
				)
			else
				inst.components.talker:Say(STRINGS.MUSHA_TALK_NEED_SPELLPOWER)
			end
		end
	else
		inst.components.talker:Say(STRINGS.MUSHA_TALK_GHOST_OOOOH)
	end
end

function Musha_Skills:PowerAttack(target)
	if self.inst.components.musha_fatiguesleep then
		self.inst.components.musha_fatiguesleep:DoDelta(1.5)
	end
	if self.inst.musha_settings.lightning_sound then
		SpawnPrefab("lightning").Transform:SetPosition(target:GetPosition():Get())
	else
		SpawnPrefab("musha_lightning").Transform:SetPosition(target:GetPosition():Get())
	end
	local fx_3 = SpawnPrefab("groundpoundring_fx")
	fx_3.Transform:SetScale(0.7, 0.7, 0.7)
	fx_3.Transform:SetPosition(target:GetPosition():Get())
	SpawnPrefab("explode_small").Transform:SetPosition(target:GetPosition():Get())

	local shocking2 = SpawnPrefab("musha_spin_fx")
	shocking2.Transform:SetPosition(self.inst:GetPosition():Get())
	if shocking2 then
		local follower = shocking2.entity:AddFollower()
		follower:FollowSymbol(self.inst.GUID, self.inst.components.combat.hiteffectsymbol, 0, 0, 0.5)
	end

	local weapon_damage = self.inst.components.combat:GetWeapon().components.weapon:GetDamage(self.inst, target)
	if self.inst.components.musha_equipbuff then
		if self.inst.components.musha_equipbuff.buff == "fire" then
			local fx = SpawnPrefab("firesplash_fx")
			fx.Transform:SetScale(0.5, 0.5, 0.5)
			fx.Transform:SetPosition(target:GetPosition():Get())
			local fx2 = SpawnPrefab("firesplash_fx")
			fx2.Transform:SetScale(0.5, 0.5, 0.5)
			fx2.Transform:SetPosition(self.inst:GetPosition():Get())
			if target.components.burnable then
				target.components.burnable:Ignite()
				target.components.health:DoDelta(-weapon_damage * self.inst.components.musha_equipbuff.bufflevel * 0.01)
			else
				target.components.health:DoDelta(-weapon_damage * self.inst.components.musha_equipbuff.bufflevel * 0.005)
			end
		elseif self.inst.components.musha_equipbuff.buff == "ice" then
			if target ~= nil and target.components.freezable then
				target.components.freezable:AddColdness(self.inst.components.musha_equipbuff.bufflevel * 0.025)
				target.components.freezable:SpawnShatterFX()
				local prefab = "icespike_fx_" .. math.random(1, 4)
				local fx = SpawnPrefab(prefab)
				local shards = math.random(0.8, 1.2)
				fx.Transform:SetScale(shards, shards, shards)
				fx.Transform:SetPosition(target:GetPosition():Get())
				target.components.health:DoDelta(-weapon_damage * self.inst.components.musha_equipbuff.bufflevel * 0.005)
			else
				local prefab = "icespike_fx_" .. math.random(1, 4)
				local fx = SpawnPrefab(prefab)
				local shards = math.random(0.8, 1.2)
				fx.Transform:SetScale(shards, shards, shards)
				fx.Transform:SetPosition(target:GetPosition():Get())
				target.components.health:DoDelta(-weapon_damage * self.inst.components.musha_equipbuff.bufflevel * 0.005)
			end
		elseif self.inst.components.musha_equipbuff.buff == "phoenix" then
			target.components.health:DoDelta(-weapon_damage * self.inst.components.musha_equipbuff.bufflevel * 0.005)
			local fx3 = SpawnPrefab("groundpoundring_fx")
			fx3.Transform:SetScale(0.3, 0.3, 0.3)
			fx3.Transform:SetPosition(target:GetWorldPosition():Get())
			if target.components.sleeper then
				target.components.sleeper:AddSleepiness(
					self.inst.components.musha_equipbuff.bufflevel * 0.03,
					self.inst.components.musha_equipbuff.bufflevel * 0.3
				)
			end
		else
			target.components.health:DoDelta(-weapon_damage * self.inst.components.musha_equipbuff.bufflevel * 0.005)
		end
	else
		target.components.health:DoDelta(-weapon_damage * self.inst.components.musha_equipbuff.bufflevel * 0.005)
	end

	if target.components.burnable and target.components.burnable:IsBurning() then
		target.components.burnable:Extinguish()
	end

	OnTaskTick(self.inst)
end

function Musha_Skills:Electric_Book(inst)
	inst.AnimState:PushAnimation("mime3", false)
	if not inst.components.musha_spellpower:CanCost(20) then
		inst.sg:GoToState("mindcontrolled")
		return
	end
	if inst.components.musha_fatiguesleep then
		inst.components.musha_fatiguesleep:DoDelta(-5)
	end
	------------------------------------------------------------------
	local x, y, z = inst.Transform:GetWorldPosition()
	local ents = TheSim:FindEntities(x, y, z, 20)
	for k, v in pairs(ents) do
		if
			v ~= nil and v.components.health and not v.components.health:IsDead() and v.entity:IsVisible() and
				v.components.combat and
				(v.components.combat.target == inst or v:HasTag("monster") or v:HasTag("werepig") or v:HasTag("frog")) and
				not v:HasTag("player") and
				not v:HasTag("companion") and
				not v:HasTag("stalkerminion") and
				not v:HasTag("smashable") and
				not v:HasTag("alignwall") and
				not v:HasTag("shadowminion")
		 then
			---------------------------------------------
			inst.SoundEmitter:PlaySound("dontstarve/rain/thunder_close")
			if inst.musha_settings.lightning_sound then
				SpawnPrefab("lightning").Transform:SetPosition(v:GetPosition():Get())
			else
				SpawnPrefab("musha_lightning").Transform:SetPosition(v:GetPosition():Get())
			end

			local fx = SpawnPrefab("firesplash_fx")
			fx.Transform:SetScale(0.5, 0.5, 0.5)
			fx.Transform:SetPosition(v:GetPosition():Get())

			if v.components.locomotor and not v:HasTag("ghost") then
				v.components.locomotor.groundspeedmultiplier = 0.4
				v.components.locomotor:StopMoving()
				if v:HasTag("spider") and not v:HasTag("spiderqueen") then
					v.sg:GoToState("hit_stunlock")
				else
					v.sg:GoToState("hit")
				end
			end
			local fx_2 = SpawnPrefab("groundpoundring_fx")
			fx_2.Transform:SetScale(0.4, 0.4, 0.4)
			fx_2.Transform:SetPosition(inst:GetPosition():Get())

			v:DoTaskInTime(
				0.3,
				function()
					SpawnPrefab("shock_fx").Transform:SetPosition(v:GetPosition():Get())
					SpawnPrefab("musha_lightning").Transform:SetPosition(v:GetPosition():Get())
					v:DoTaskInTime(
						0.4,
						function()
							local fx_3 = SpawnPrefab("groundpoundring_fx")
							fx_3.Transform:SetScale(0.3, 0.3, 0.3)
							fx_3.Transform:SetPosition(v:GetPosition():Get())
						end
					)

					if v.components.combat and not v:HasTag("companion") then
						v.components.combat:SuggestTarget(inst)
					end

					if not v:HasTag("lightninggoat") then
						v.AnimState:SetBloomEffectHandle("")
					end

					local shocking = SpawnPrefab("musha_spin_fx")
					shocking.Transform:SetPosition(v:GetPosition():Get())
					if shocking then
						local follower = shocking.entity:AddFollower()
						follower:FollowSymbol(v.GUID, v.components.combat.hiteffectsymbol, 0, 0, 0.5)
					end

					v.components.health:DoDelta(-20 - self.currentlevel * 0.5)

					local debuff = SpawnPrefab("musha_debuff_short")
					debuff.Transform:SetPosition(v:GetPosition():Get())
					if debuff then
						local follower = debuff.entity:AddFollower()
						if not v:HasTag("cavedweller") then
							follower:FollowSymbol(v.GUID, v.components.combat.hiteffectsymbol, 0, -50, 0.5)
						else
							follower:FollowSymbol(v.GUID, "body", 0, -50, 0.5)
						end
						v.musha_electrictask =
							v:DoPeriodicTask(
							0.25,
							function(target)
								if target.components.health and not target.components.health:IsDead() then
									SpawnPrefab("sparks").Transform:SetPosition(v:GetPosition():Get())
									target.components.health:DoDelta(-4 + self.currentlevel * 0.1)
									if v.components.locomotor and not v:HasTag("ghost") then
										v.components.locomotor:StopMoving()
										if v:HasTag("spider") and not v:HasTag("spiderqueen") then
											v.sg:GoToState("hit_stunlock")
										else
											v.sg:GoToState("hit")
										end
									end
								end
							end
						)
					end
					if v.musha_electrictask_cancel then
						v.musha_electrictask_cancel:Cancel()
					end
					v.musha_electrictask_cancel =
						v:DoTaskInTime(
						12,
						function()
							if v.musha_electrictask then
								v.components.locomotor.groundspeedmultiplier = 1
								v.musha_electrictask:Cancel()
								v.musha_electrictask = nil
								debuff:Remove()
								v.musha_electrictask_cancel:Cancel()
								v.musha_electrictask_cancel = nil
							end
						end
					)
				end
			)
		end
	end
end

return Musha_Skills
